﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Ionic;
using Ionic.Zip;

namespace ETWebApi2.Models
{
    public class DotNetZip
    {
        /// <summary>
        /// 把多个文件压缩为一个ZIP文件,以便下载
        /// </summary>
        /// <param name="list">list两个为一组,第一个市</param>
        /// <param name="pathName">压缩后的文件全路径</param>
        /// <returns>成功：true/失败：false</returns>
        public static bool CompressMulti(int userID, List<string> list, ref string zipName)
        {
            try
            {
                using (ZipFile zip = new ZipFile(Encoding.Default))//设置编码，解决压缩文件时中文乱码
                {
                    //每个文件由两个字符串组成,第一个是文件路径,第二个是文件的正确名字
                    for (int i = 0; i < list.Count; i += 2)
                    {
                        if (File.Exists(list[i]))//如果文件存在
                        {
                            ZipEntry ze = zip.AddFile(list[i], "");//这里注意要用2个参数的AddFile 并且将第二个参数置空 否则 压缩包将中会有目录文件夹
                            string name = list[i + 1];
                            for (int k = 1; k < i; k += 2)
                            {
                                if (list[k] == name)
                                {
                                    if (name.Length > 4)
                                        name = string.Format("{0}({1}){2}", name.Substring(0, name.Length - 4), i / 2, name.Substring(name.Length - 4, 4));
                                    else
                                        name = (i / 2).ToString() + ":" + name;
                                    break;
                                }
                            }
                            ze.FileName = name;
                        }
                        else
                        {
                            zipName = string.Format("第{0}个文件不存在", i / 2 + 1);
                            return false;
                        }
                    }

                    //把多个文件压缩为一个临时ZIP文件,以便下载,因为用于下载,所以不能删除
                    //但是因为每个人至多产生一个临时文件,所以不删除,也不会有什么问题
                    string tempFilePath = HttpContext.Current.Server.MapPath("/file") + "\\TEMP\\";
                    zipName = tempFilePath + userID.ToString() + ".zip";

                    if (!Directory.Exists(tempFilePath))//临时文件夹是否存在
                    {
                        Directory.CreateDirectory(tempFilePath);
                    }
                    else
                    {
                        if (File.Exists(zipName))
                            File.Delete(zipName);
                    }

                    zip.Save(zipName);//压缩

                    return true;
                }
            }
            catch (Exception e)
            {
                zipName = "压缩失败";
                zipName = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 压缩单个文件 
        /// </summary>
        /// <param name="srcFilePath">源文件全路径名</param>
        /// <param name="desFileName">压缩文件内部文件的名字</param>
        ///  <param name="zipName">返回,压缩文件的全路径名</param>
        /// <returns></returns>
        public static bool CompressSingle(int userID, string srcFilePath, string desFileName, ref string zipName)
        {
            List<string> pathList = new List<string>();
            pathList.Add(srcFilePath);
            pathList.Add(desFileName);

            return CompressMulti(userID, pathList, ref zipName);
        }

        /// <summary>
        /// 解压指定的压缩包
        /// </summary>
        /// <param name="strZipPath">待解压的ZIP文件</param>
        /// <param name="strUnZipPath">解压目录</param>
        /// <param name="overWrite">是否覆盖</param>
        /// <param name="overWrite">压缩包内部的文件名</param>
        /// <returns></returns>
        public static bool DecomPression(string strZipPath, string strUnZipPath, bool overWrite, List<string> fileNameList)
        {
            try
            {
                ReadOptions options = new ReadOptions();
                options.Encoding = Encoding.Default;//设置编码，解决解压文件时中文乱码
                using (ZipFile zip = ZipFile.Read(strZipPath, options))
                {
                    if (!Directory.Exists(strUnZipPath))
                    {
                        Directory.CreateDirectory(strUnZipPath);
                    }
                    foreach (ZipEntry entry in zip)//压缩包内的对象逐个解压 也可以用 zip.ExtractAll 一次性解压全部
                    {
                        fileNameList.Add(entry.FileName);
                        if (overWrite)
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.OverwriteSilently);//解压文件，如果已存在就覆盖
                        }
                        else
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.DoNotOverwrite);//解压文件，如果已存在不覆盖
                        }
                    }
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        /// <summary>
        /// 对压缩的文件流进行解压（目前没测试过）
        /// </summary>
        /// <param name="strZipPath">待解压的ZIP文件流</param>
        /// <param name="strUnZipPath">解压目录</param>
        /// <param name="overWrite">是否覆盖</param>
        /// <returns></returns>
        public static bool DecomStream(Stream strZipStream, string strUnZipPath, bool overWrite)
        {
            try
            {
                ReadOptions options = new ReadOptions();
                options.Encoding = Encoding.Default;//设置编码，解决解压文件时中文乱码
                using (ZipFile zip = ZipFile.Read(strZipStream, options))
                {
                    if (!Directory.Exists(strUnZipPath))
                    {
                        Directory.CreateDirectory(strUnZipPath);
                    }
                    foreach (ZipEntry entry in zip)//压缩包内的对象逐个解压 也可以用 zip.ExtractAll 一次性解压全部
                    {

                        if (overWrite)
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.OverwriteSilently);//解压文件，如果已存在就覆盖
                        }
                        else
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.DoNotOverwrite);//解压文件，如果已存在不覆盖
                        }
                    }
                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 递归删除文件夹目录及文件 
        /// </summary>
        /// <param name="path"></param>  
        public static void DeleteFolder(string path)
        {
            string dir = path;
            if (System.IO.Directory.Exists(dir)) //如果存在这个文件夹删除之 
            {
                foreach (string d in System.IO.Directory.GetFileSystemEntries(dir))
                {
                    if (System.IO.File.Exists(d))
                        System.IO.File.Delete(d); //直接删除其中的文件                        
                    else
                        DeleteFolder(d); //递归删除子文件夹 
                }
                System.IO.Directory.Delete(dir, true); //删除已空文件夹                 
            }
        }

        /// <summary>
        ///删除文件 
        /// </summary>
        /// <param name="path">文件路径</param>
        public static bool DeleteFile(string path)
        {
            if (System.IO.File.Exists(path))
            {
                System.IO.File.Delete(path); //直接删除文件  
                return true;
            }
            else { return false; }
        }
    }
}